home *** CD-ROM | disk | FTP | other *** search
- # Standard main loop for *all* STDWIN applications.
- # This requires that applications:
- # - register their windows on creation and unregister them when closed
- # - have a 'dispatch' function as a window member
-
-
- import stdwin, stdwinq
- from stdwinevents import *
-
-
- # List of windows known to the main loop.
- #
- windows = []
-
-
- # Last window that ever received an event
- #
- last_window = None
-
-
- # Function to register a window.
- #
- def register(win):
- # First test the dispatch function by passing it a null event --
- # this catches registration of unconforming windows.
- win.dispatch((WE_NULL, win, None))
- if win not in windows:
- windows.append(win)
-
-
- # Function to unregister a window.
- # It is not an error to unregister an already unregistered window
- # (this is useful for cleanup actions).
- #
- def unregister(win):
- global last_window
- if win == last_window:
- last_window = None
- if win in windows:
- windows.remove(win) # Not in 0.9.1
- # 0.9.1 solution:
- #for i in range(len(windows)):
- # if windows[i] = win:
- # del windows[i]
- # break
-
-
- # Interfaces used by WindowSched.
- #
- def countwindows():
- return len(windows)
- #
- def anywindow():
- if windows:
- return windows[0]
- else:
- return None
-
-
- # NEW: register any number of file descriptors
- #
- fdlist = []
- select_args = None
- select_handlers = None
- #
- def registerfd(fd, mode, handler):
- if mode not in ('r', 'w', 'x'):
- raise ValueError, 'mode must be r, w or x'
- if type(fd) <> type(0):
- fd = fd.fileno() # If this fails it's not a proper select arg
- for i in range(len(fdlist)):
- if fdlist[i][:2] == (fd, mode):
- raise ValueError, \
- '(fd, mode) combination already registered'
- fdlist.append((fd, mode, handler))
- make_select_args()
- #
- def unregisterfd(fd, *args):
- if type(fd) <> type(0):
- fd = fd.fileno() # If this fails it's not a proper select arg
- args = (fd,) + args
- n = len(args)
- for i in range(len(fdlist)):
- if fdlist[i][:n] == args:
- del fdlist[i]
- make_select_args()
- #
- def make_select_args():
- global select_args, select_handlers
- rlist, wlist, xlist = [], [], []
- rhandlers, whandlers, xhandlers = {}, {}, {}
- for fd, mode, handler in fdlist:
- if mode == 'r':
- rlist.append(fd)
- rhandlers[`fd`] = handler
- if mode == 'w':
- wlist.append(fd)
- whandlers[`fd`] = handler
- if mode == 'x':
- xlist.append(fd)
- xhandlers[`fd`] = handler
- if rlist or wlist or xlist:
- select_args = rlist, wlist, xlist
- select_handlers = rhandlers, whandlers, xhandlers
- else:
- select_args = None
- select_handlers = None
- #
- def do_select():
- import select
- reply = apply(select.select, select_args)
- for mode in 0, 1, 2:
- list = reply[mode]
- for fd in list:
- handler = select_handlers[mode][`fd`]
- handler(fd, 'rwx'[mode])
-
-
- # Event processing main loop.
- # Return when there are no windows left, or when an unhandled
- # exception occurs. (It is safe to restart the main loop after
- # an unsuccessful exit.)
- # Python's stdwin.getevent() turns WE_COMMAND/WC_CANCEL events
- # into KeyboardInterrupt exceptions; these are turned back in events.
- #
- recursion_level = 0 # Hack to make it reentrant
- def mainloop():
- global recursion_level
- recursion_level = recursion_level + 1
- try:
- stdwin_select_handler() # Process events already in queue
- while 1:
- if windows and not fdlist:
- while windows and not fdlist:
- try:
- event = stdwinq.getevent()
- except KeyboardInterrupt:
- event = (WE_COMMAND, \
- None, WC_CANCEL)
- dispatch(event)
- elif windows and fdlist:
- fd = stdwin.fileno()
- if recursion_level == 1:
- registerfd(fd, 'r', stdwin_select_handler)
- try:
- while windows:
- do_select()
- stdwin_select_handler()
- finally:
- if recursion_level == 1:
- unregisterfd(fd)
- elif fdlist:
- while fdlist and not windows:
- do_select()
- else:
- break
- finally:
- recursion_level = recursion_level - 1
-
-
- # Check for events without ever blocking
- #
- def check():
- stdwin_select_handler()
- # XXX Should check for socket stuff as well
-
-
- # Handle stdwin events until none are left
- #
- def stdwin_select_handler(*args):
- while 1:
- try:
- event = stdwinq.pollevent()
- except KeyboardInterrupt:
- event = (WE_COMMAND, None, WC_CANCEL)
- if event is None:
- break
- dispatch(event)
-
-
- # Run a modal dialog loop for a window. The dialog window must have
- # been registered first. This prohibits most events (except size/draw
- # events) to other windows. The modal dialog loop ends when the
- # dialog window unregisters itself.
- #
- passthrough = WE_SIZE, WE_DRAW
- beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU
- #
- def modaldialog(window):
- if window not in windows:
- raise ValueError, 'modaldialog window not registered'
- while window in windows:
- try:
- event = stdwinq.getevent()
- except KeyboardInterrupt:
- event = WE_COMMAND, None, WC_CANCEL
- etype, ewindow, edetail = event
- if etype not in passthrough and ewindow <> window:
- if etype in beeping:
- stdwin.fleep()
- continue
- dispatch(event)
-
-
- # Dispatch a single event.
- # Events for the no window in particular are sent to the active window
- # or to the last window that received an event (these hacks are for the
- # WE_LOST_SEL event, which is directed to no particular window).
- # Windows not in the windows list don't get their events:
- # events for such windows are silently ignored.
- #
- def dispatch(event):
- global last_window
- if event[1] == None:
- active = stdwin.getactive()
- if active: last_window = active
- else:
- last_window = event[1]
- if last_window in windows:
- last_window.dispatch(event)
-
-
- # Dialog base class
- #
- class Dialog:
- #
- def __init__(self, title):
- self.window = stdwin.open(title)
- self.window.dispatch = self.dispatch
- register(self.window)
- #
- def close(self):
- unregister(self.window)
- del self.window.dispatch
- self.window.close()
- #
- def dispatch(self, event):
- etype, ewindow, edetail = event
- if etype == WE_CLOSE:
- self.close()
-
-
- # Standard modal dialogs
- # XXX implemented using stdwin dialogs for now
- #
- def askstr(prompt, default):
- return stdwin.askstr(prompt, default)
- #
- def askync(prompt, yesorno):
- return stdwin.askync(prompt, yesorno)
- #
- def askfile(prompt, default, new):
- return stdwin.askfile(prompt, default, new)
- #
- def message(msg):
- stdwin.message(msg)
-